let isDone: boolean = false; // 定义 布尔型
let num: number = 0; // 定义 数字类型
let num1: number = 3;
let str: string = '0'; // string
// 
/**
 * 定义数组类型的数据
 * 两种方式：
 *  1. list: type[] = [];
 *  2. list Array< type > = [];
 *  如果不确定 数据类型 指定数据类型为 any
 *  定义了 a: any, a 为任意类型的数据
 */
// 指定 数组元素类型为 数字
let list: number[] = [ 1, 2, 3]; // 定义数组类型，为数字类型
let list1: Array<number> = [ 1, 2, 3];
// 指定数组类型的 元素类型
let list2: object[] = [{ name: 'name'},{ name: 'name' }];
let list3: Array<object> = [ { age: 'age'}, { age: 'age' }];

let list4: string[] = [ '1', 'age', 'name' ];
let list5: Array<string> = [ '1', 'age', 'name' ];

//=============================== 枚举类型 =========================
// 枚举类型 通过下表访问
// 可以重置下表的 起始位置
enum Color { red=2, green, blue };
let colorName: string = Color[1];
let index:Color = Color.green; // 获取 枚举类型的下标


/*============================ 函数定义类型定义 =====================
    1. 参数需要一一对应， 类型和个数需对应
    2. 在圆括号后面指定 函数返回类型， 遵循宁缺毋滥的原则
    3. 可选参数， 使用 ？ 在注解前
    4. 默认参数， 使用 = 在注解后
    5. 可变参数， 使用 ... 
    6. this 的使用
    7. 函数重载
==================================================================*/
function emptyFn(a: number, b: Array<number> ): Array<any>{
    return [ undefined, null, 0, false ]
    // return 1 + b.reduce((a, b ) => a + b ) + '';
}

const fn2 = function( age: number, sex: string ): void{}

const fn3: ( name: string, age: number ) => string = (n: string, a: number): string => {
    return n;
} 

// 3. 可选参数， 使用 ？ 在注解前
const f4 = ( name: string, age?: number): number => {
    return age;
}
console.log( f4( 'lifei' ) );

// 4. 默认参数， 使用 = 在注解后
const fn1 = (  age: number, hobby:Array<string>, name: string="name" ): string=>{
    return name;
}

// 5. 可变参数， 使用 ... 
const fn5 = ( name: string, ...rest:any[]) => {
    console.log( name, rest.join( '' ));
}
console.log( fn5( 'name', '=>', '', '0', true, undefined, null, 0), 'f5' );

// 6. this 的使用
const f6 = {
    name: [ 'q', 'w', 'e', 'r' ],
    getName: function(){
        return () => {
            const i = Math.floor( Math.random() * 4 )
            return {
                n: this.name[ i ]
            }
        }
    }
}

console.log( f6.getName()().n, 'f6' );

// 7. 函数重载

function overload( name: string): string;
function overload( name: number): number;
function overload( name: any ): any {
    if( name && typeof name === 'string' ){
        return '我是--字符串--类型'
    }else{
        return '我是--数字--类型';
    }
}
console.log( overload(1), overload( '1' ) );



/*============================ class类 ================================
    1. 定义 对象属性 指定属性类型
    2. 修饰符 public private 
        当指定为 public 共享 成员， private  所有 继承的 类 都不能被访问到
======================================================================*/

class Person{
    private name: string;
    age: number;
    json: {
        name:' 111 ',
        age: '123'
    }
    constructor( name: string, age: number ){
        this.name = name;
        this.age = age;
    }
    print(){
        return this.name + ' : ' + this.age + this.json;
    }
}


let p = new Person( 'lifei', 20 );

// console.log( p.print() );


class Student extends Person{
    school: string;
    constructor( school: string, name: string ){
        super( 'name', 18 );
        this.school = school;
    }
    print(){
        return ' -> ' + this.age + ' -> ' + this.school;
    }
}

let s = new Student( 'school', 'name' );
console.log( s.print(), 'class1' )






// const overload = ( param: string ): string

// console.log( fn1( 1, ['1']), 'fn1' );

// emptyFn( 1, [ 1, 2 ] );

// //================================ 接口 ============================

// interface Person { // Person 是一种自定义的数据类型
//     firstName: string;
//     lastName: string;
// }

// function greeter(person: Person) {
//     return "Hello, " + person.firstName + " " + person.lastName;
// }

// let user = { firstName: "", lastName: "User" };

// document.body.innerHTML = greeter(user);
/**================================================= */






